﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ScreenMonitor.Common.File
{

    /// <summary>
    /// 为文件收发的请求类型提供枚举
    /// </summary>
    public enum FileRequestType
    {
        /// <summary>
        /// 请求打开文件，一般为初次请求使用
        /// </summary>
        Open,
        /// <summary>
        /// 请求打开文件，当文件不存在时自动创建
        /// </summary>
        OpenOrCreate,
        /// <summary>
        /// 请求读取文件
        /// </summary>
        Read,
        /// <summary>
        /// 请求写文件
        /// </summary>
        Write,
        /// <summary>
        /// 请求关闭文件
        /// </summary>
        Close,
        /// <summary>
        /// 操作出错，请求处理错误
        /// </summary>
        Error,
        /// <summary>
        /// 终止一个文件传输
        /// </summary>
        Stop
    }

    /// <summary>
    /// 为文件收发的请求步骤提供信息存储
    /// </summary>
    public sealed class FileRequestObject
    {
        private static object StaticLockObj = new object();
        private object LockObj = new object();

        #region==========属性==========

        /// <summary>
        /// 文件请求类型
        /// </summary>
        public FileRequestType ReauestType { get; set; }
        /// <summary>
        /// 文件路径
        /// </summary>
        public string FilePath { get; private set; }
        /// <summary>
        /// 请求端分配的请求ID
        /// </summary>
        public int RequestID { get; internal set; }
        /// <summary>
        /// 回复端分配的回复ID
        /// </summary>
        public int ResponceID { get; internal set; }
        /// <summary>
        /// 获取或设置文件的当前偏移量
        /// </summary>
        public long FileOffset { get; set; }
        /// <summary>
        /// 获取或设置文件的当前的缓冲区数据，当请求为写入请求时为请求数据，当请求为错误请求时为错误字符串的字节封装
        /// </summary>
        public byte[] Buffer { get; set; }
        /// <summary>
        /// 表示发送该请求包含的用户自定义数据
        /// </summary>
        public object Tag { get;private set; }
        #endregion

        #region========构造函数========
        /// <summary>
        /// 通过指定的文件路径构造文件请求实例
        /// </summary>
        /// <param name="FilePath"></param>
        public FileRequestObject(string FilePath,object Tag)
        {
            this.FilePath = FilePath;
            this.Buffer = new byte[0];
            this.FileOffset = 0;
            this.Tag = Tag;
            this.RequestID = -1;
            this.ResponceID = -1;
        }
        #endregion

        #region========公有函数========

        public byte[] ToByte()
        {
            lock (LockObj)
            {
                MemoryStream stream = new MemoryStream();
                BinaryWriter bw = new BinaryWriter(stream);
                bw.Write((int)this.ReauestType);
                bw.Write(this.FilePath);
                bw.Write(this.RequestID);
                bw.Write(this.ResponceID);
                bw.Write(this.FileOffset);
                bw.Write(this.Buffer.Length);
                bw.Write(this.Buffer, 0, this.Buffer.Length);
                bw.Flush();
                byte[] r = stream.ToArray();
                return r;
            }
        }

        public static FileRequestObject FromByte(byte[] Data,object Connection)
        {
            lock (StaticLockObj)
            {
                MemoryStream stream = new MemoryStream(Data);
                BinaryReader br = new BinaryReader(stream);
                FileRequestObject r = new FileRequestObject("", Connection);
                r.ReauestType = (FileRequestType)br.ReadInt32();
                r.FilePath = br.ReadString();
                r.RequestID = br.ReadInt32();
                r.ResponceID = br.ReadInt32();
                r.FileOffset = br.ReadInt64();
                int bufferlen = br.ReadInt32();
                r.Buffer = br.ReadBytes(bufferlen);
                br.Close();
                return r;
            }
        }

        #endregion

    }
}
